package com.example.demo.filters;

import com.example.demo.domain.ResultMessage;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import io.github.resilience4j.reactor.circuitbreaker.operator.CircuitBreakerOperator;
import io.vavr.control.Try;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * 多服务熔断过滤器
 */
@Component
public class CircuitBreakerFilter implements GatewayFilter, Ordered {

    @Autowired
    private CircuitBreakerRegistry circuitBreakerRegistry;
    
    // 服务路径前缀与断路器名称的映射
    private static final Map<String, String> SERVICE_BREAKER_MAP = new HashMap<>();
    
    // 初始化服务与断路器的映射关系
    static {
        SERVICE_BREAKER_MAP.put("/user/", "userService");
        SERVICE_BREAKER_MAP.put("/product/", "productService");
        SERVICE_BREAKER_MAP.put("/fund/", "fundService");
        // 可以根据需要添加更多服务映射
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取请求路径
        String path = exchange.getRequest().getURI().getPath();
        
        // 确定使用哪个断路器
        String breakerName = determineCircuitBreakerName(path);
        
        // 获取对应的断路器，如果不存在则使用默认断路器
        CircuitBreaker circuitBreaker;
        try {
            circuitBreaker = circuitBreakerRegistry.circuitBreaker(breakerName);
        } catch (Exception e) {
            // 如果指定的断路器不存在，使用userService作为默认断路器
            circuitBreaker = circuitBreakerRegistry.circuitBreaker("userService");
        }

        CircuitBreaker finalCircuitBreaker = circuitBreaker;
        Function<Throwable, Mono<Void>> fallback = throwable -> {
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.SERVICE_UNAVAILABLE);
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);

            ResultMessage result = new ResultMessage(false, "服务[" + finalCircuitBreaker.getName() + "]暂时不可用，请稍后再试");
            String body = toJson(result);

            DataBuffer dataBuffer = response.bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8));
            return response.writeWith(Mono.just(dataBuffer));
        };

        return Try.of(() -> chain.filter(exchange).transform(CircuitBreakerOperator.of(finalCircuitBreaker))
                .onErrorResume(fallback)).getOrElseGet(fallback);
    }

    /**
     * 根据请求路径确定使用哪个断路器
     * @param path 请求路径
     * @return 断路器名称
     */
    private String determineCircuitBreakerName(String path) {
        return SERVICE_BREAKER_MAP.entrySet().stream()
                .filter(entry -> path.startsWith(entry.getKey()))
                .map(Map.Entry::getValue)
                .findFirst()
                .orElse("userService"); // 如果没有匹配的服务，使用userService作为默认断路器
    }

    @Override
    public int getOrder() {
        return -100; // 确保在RateLimiter之前执行
    }

    private String toJson(ResultMessage result) {
        ObjectMapper mapper = new ObjectMapper();
        String body = null;
        try {
            body = mapper.writeValueAsString(result);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return body;
    }
}